import json
import time
import csv
from curl_cffi import requests
import subprocess
from functools import partial
from tqdm import tqdm
import execjs
import hashlib

subprocess.Popen = partial(subprocess.Popen, encoding="utf-8")
# 使用execjs编译JS脚本
with open("h5st514.js", "r", encoding="utf-8") as f:
    js = f.read()

js_com = execjs.compile(js)


def sha_256(message):
    return hashlib.sha256(message.encode("utf-8")).hexdigest()


def generate_h5st(params):
    body_str = params["body"]
    body = json.loads(body_str) if isinstance(body_str, str) else body_str
    # 构建 boddy 数据
    boddy = {
        "keyword": body["keyword"],
        "stock": body["stock"],
        "pvid": body["pvid"],
        "isList": body["isList"],
        "page": body["page"],
        "s": body["s"],
        "click": body["click"],
        "log_id": body["log_id"],
        "show_items": body["show_items"],
    }
    # 构建请求参数
    a = {
        "appid": params.get("appid", "search-pc-java"),
        "body": sha_256(json.dumps(boddy, separators=(",", ":"))),
        "clientVersion": params.get("clientVersion", "1.0.0"),
        "client": params.get("client", "pc"),
        "functionId": params.get("functionId", "pc_search_s_new"),
        "t": int(time.time() * 1000),  # 当前时间戳
    }
    # 生成 h5st
    h5st = js_com.call("getH5st", a)
    return h5st


# API配置
url = "https://api.m.jd.com/"
params = {
    "body": "{\"keyword\":\"电脑\",\"stock\":\"1\",\"pvid\":\"070f9cfaaed24aaa93d1140ded5752a9\",\"isList\":0,\"page\":\"3\",\"s\":\"54\",\"click\":\"0\",\"log_id\":\"1752230495085.3450\",\"show_items\":\"\"}",
}
params_template = {
    "appid": "search-pc-java",
    "functionId": "pc_search_s_new",
    "client": "pc",
    "clientVersion": "1.0.0",
    "loginType": "3",
    "uuid": "143920055.1751545604909534518369.1751545604.1752224288.1752226846.4",
    "x-api-eid-token": "jdd03GNWKXUTIE6HBK6NALGSXSPDIJB4FOSTK2HH5HNAWZAUUMF5JYQCGOIB4252C7TECGDOSXSGLUC74Z5SQVPIKNU2LBEAAAAMX7EJXZGIAAAAACAK77ULHDATEXEX",
    "area": "19_1607_0_0",
}

headers = {
    "accept": "*/*",
    "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,ar;q=0.7",
    "cache-control": "no-cache",
    "origin": "https://search.jd.com",
    "pragma": "no-cache",
    "priority": "u=1, i",
    "referer": "https://search.jd.com/",
    "sec-ch-ua": "\"Not)A;Brand\";v=\"8\", \"Chromium\";v=\"138\", \"Microsoft Edge\";v=\"138\"",
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": "\"Windows\"",
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "same-site",
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0",
    "x-referer-page": "https://search.jd.com/Search",
    "x-rp-client": "h5_1.0.0"
}
cookies = {
    "b_webp": "1",
    "b_avif": "1",
    "jcap_dvzw_fp": "_HIVLiZCIEZDIcHwXjPU43al5uvsYIwPfs4O6VE9nqABptbi3ASG0seWjzU_o2F4bpTtKrH1VphdN9RwziykSA==",
    "whwswswws": "",
    "__jdv": "122270672%7Cdirect%7C-%7Cnone%7C-%7C1751545604909",
    "__jdu": "1751545604909534518369",
    "pinId": "briEibRb-h1YgxkG81uaz7V9-x-f3wj7",
    "pin": "jd_7eac037a858fc",
    "unick": "jd_8js7q5tn2s7n2h",
    "_tp": "aO5XtogPiplRTZPyN6P5Vkd5JC%2FQJe7kEmh0g0oTaNI%3D",
    "_pst": "jd_7eac037a858fc",
    "ipLoc-djd": "19-1607-0-0",
    "shshshfpa": "ab96e4b0-82d6-a907-9206-6c096fe807bb-1751545628",
    "shshshfpx": "ab96e4b0-82d6-a907-9206-6c096fe807bb-1751545628",
    "areaId": "19",
    "PCSYCityID": "CN_440000_440300_0",
    "autoOpenApp_downCloseDate__jd_czlogin_openapp_": "1752224419174_1",
    "b_dw": "1912",
    "b_dh": "954",
    "b_dpr": "1",
    "autoOpenApp_downCloseDate_jd_homePage": "1752226834147_1",
    "autoOpenApp_downCloseDate_auto": "1752226845692_1800000",
    "commonAddress": "0",
    "regionAddress": "1%2C72%2C55674%2C0",
    "mt_xid": "V2_52007VwMUVl1cV14YSBxUBG8HEFdZWFtYGEEpXVBjCkcCCAhOWBsdGUAAZQAUTg1eVFMDHhoLDDdQEQBeXFBdL0oYXwF7AhROXVhDWhlCHFQOZwMiUG1YYlMfSB1eBmMEFFJcX1ZZGk4RWQ1XAxFRXw%3D%3D",
    "warehistory": "\"100124552423,10092745719292,100124552423,100126228944,\"",
    "autoOpenApp_downCloseDate_autoOpenApp_autoPromptly": "1752227819923_1",
    "pt_st": "1_b4icbLDrQArn0cxP2HrWd52OePOExea0Jf3d5GU7ZDNxycxozqafTLZP8UFvD2yptQsomwf2-UYVZyrTC5wQqynLrLGiyG3q8nI6i5hSWFl4AAeNWC95FX4i0R71LSWFqJ2DvHQ2cldUl8WEZDlVz6MZZ3lMJJeVb4ISQL_qfGpqpLc1BYbrikhDMRA9vTqn61nU9HDMgoBQNAqt7W5KfiNomTyxnBlLMxruopZY",
    "TrackID": "1niKUQYb-rtx_W8NqIr7p794udrddHlWmBsM7VCqfFSRqsnFBOKtSNGv5MwSaaIptwAekpQGc-lVbatyIbIIsdh6kB0gSXD0Vf_HOAU3UPpgyNscP-uKG7aFXOVOpu3Hz",
    "thor": "2B3FAB022DDA7FFF772855629D82E8BA86B6B654FC776E1930AA7FEB1EB3100E4352BA9EF36DB2CA5363601A26FB8D56926934F02FEC214A855D33E9523DF9BBF6219112C431FBD129D5E5F946C5285F4F5B6BCB9C68A64458D0B167F141477BCC221C42AC5B82E714C37179E720FA1CA416456728D98223977A00EC6720051F59117BA692A7FA2CB8A8C792545F0FC0C1CB9B05CAF59D31B40631A5DF1C0593",
    "light_key": "AASBKE7rOxgWQziEhC_QY6yaY-qjKdTSlPyvgw1EnJwRdrY19x9HuXOKE36tg6wrJUawo6E8",
    "ceshi3.com": "000",
    "jsavif": "1",
    "mail_times": "2%2C2",
    "cn": "12",
    "__jda": "143920055.1751545604909534518369.1751545604.1752224288.1752226846.4",
    "__jdc": "143920055",
    "flash": "3_dyy4bqyrTzoOfgzu3BgvyI6kgqjOhWPMXd9J53g7d9_Xn74mwcje38P5P3_wCCq1Adl05_EIOtC3WpunPsq30UjU9hO9PLLfPd3g7r-_fyjmUJPj4-vfeJitWw14VGNDreW9i6aHR-FVJEs5twmWqKEuDC8Wc_xAAw-t6nSxKbfante8GfikBq**",
    "mba_muid": "1751545604909534518369",
    "mba_sid": "17522304800982096403667.1",
    "__jd_ref_cls": "LoginDisposition_Go",
    "x-rp-evtoken": "mGW9U4qbzsaBdCMe70m9pPpZnwqHxne-iYAYOTBLEhMJmxWxfydAPo5hMr9daKBQnh01yQ18NJT2QagmUN9GgQ%3D%3D",
    "__jdb": "143920055.49.1751545604909534518369|4.1752226846",
    "3AB9D23F7A4B3CSS": "jdd03GNWKXUTIE6HBK6NALGSXSPDIJB4FOSTK2HH5HNAWZAUUMF5JYQCGOIB4252C7TECGDOSXSGLUC74Z5SQVPIKNU2LBEAAAAMX7EJXZGIAAAAACAK77ULHDATEXEX",
    "_gia_d": "1",
    "shshshfpb": "BApXST-sb-vJAYEqgcJFHsyDPBX7ULrZhBhMVUQdq9xJ1MppMe462",
    "3AB9D23F7A4B3C9B": "GNWKXUTIE6HBK6NALGSXSPDIJB4FOSTK2HH5HNAWZAUUMF5JYQCGOIB4252C7TECGDOSXSGLUC74Z5SQVPIKNU2LBE",
    "sdtoken": "AAbEsBpEIOVjqTAKCQtvQu17mO4b_UzjfTt8CvhsgoyTTSFRi6bmUEOYYrNNAcAd9RhlPmfh5W1aGQN8YbhLo0w2l1ONsej375VeGYwnzuATG1HN8VYq4uaFM5d_HuXs3trN4La-8Do"
}


def read_keywords_from_csv(file_path):
    """从CSV文件中读取kw字段的关键词"""
    keywords = []
    with open(file_path, "r", encoding="utf-8") as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            if "kw" in row:
                keywords.append(row["kw"])
    return keywords


# 主流程
def main(csv_file):
    keywords = read_keywords_from_csv(csv_file)
    total_requests = 0
    successful_requests = 0

    for keyword in tqdm(keywords[:100], desc="Processing", unit="keyword"):
        params = params_template.copy()
        total_requests += 1
        params["body"] = json.dumps(
            {
                "keyword": keyword,
                "stock": "1",
                "pvid": "070f9cfaaed24aaa93d1140ded5752a9",
                "isList": 0,
                "page": "1",  # 可以调整页码
                "s": "54",
                "click": "0",
                "log_id": "1752230495085.3450",  # 当前时间戳
                "show_items": "",
            }
        )

        params["h5st"] = generate_h5st(params)

        attempt = 0
        while attempt < 3:  # 重试3次
            try:
                response = requests.get(
                    url, headers=headers, cookies=cookies, params=params
                )
                response.raise_for_status()  # 抛出异常用于非200响应

                if response.status_code == 200:
                    print(f"成功请求关键词: {keyword}，响应: {response.text[:600]},响应码: {response.status_code}")
                    if "验证" in response.text:
                        raise Exception(f"验证码出现，当前次数:{successful_requests}")
                    successful_requests += 1  # 统计成功请求次数

                else:  # 检测非200状态
                    print(
                        f"非正常响应 {response.status_code}，停止程序。当前次数:{successful_requests} 当前响应:{response.text}")
                    break

                time.sleep(60)  # 间隔10秒
                break  # 请求成功，退出重试循环
            except requests.HTTPError as e:
                print(f"网络错误: {e}，准备重试...")
                attempt += 1
                time.sleep(5)  # 延时后重试
            except Exception as e:
                print(f"出现异常: {e}，停止程序。")
                break

    # 打印统计结果
    print(f"\n总请求次数: {total_requests}")
    print(f"成功请求次数: {successful_requests}")


if __name__ == "__main__":
    main("keywords.csv")  # 替换为你的CSV文件路径
